package org.budo.support.lang.util;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.List;

import org.budo.support.slf4j.Slf4j;
import org.slf4j.Logger;

/**
 * @author limingwei
 * @date 2016年6月6日 下午2:54:32
 */
public class ProcessUtil {
    private static final Logger log = Slf4j.getLogger();

    public static Integer getCurrentProcessId() {
        RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
        Object jvm = ReflectUtil.getFieldValue(runtime, "jvm"); // VMManagementImpl

        Integer pid = ReflectUtil.invokeGet(jvm, "processId"); // 方法名为getProcessId
        return pid;
    }

    public static String getCurrentProcessName() {
        RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
        return runtimeMXBean.getName();
    }

    public static Long getStartTime() {
        RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
        return runtimeMXBean.getStartTime();
    }

    public static InputStream runCommand(List<String> command) {
        log.info("#30 runCommand " + StringUtil.join(command, " "));

        ProcessBuilder builder = new ProcessBuilder();
        builder.command(command);
        builder.redirectErrorStream(true);

        Process process = startProcessBuilder(builder);
        InputStream inputStream = process.getInputStream();
        byte[] byteArray = IoUtil.toByteArray(inputStream);

        process.destroy();
        return new ByteArrayInputStream(byteArray);
    }

    private static Process startProcessBuilder(ProcessBuilder processBuilder) {
        try {
            return processBuilder.start();
        } catch (Throwable e) {
            throw new RuntimeException("#72 processBuilder=" + processBuilder //
                    + ", command=" + StringUtil.join(processBuilder.command(), " ") //
                    + ", e=" + e, e);
        }
    }

    public static ThreadInfo[] getThreadInfos(int stackTraceMaxDepth) {
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        long[] threadIds = threadMXBean.getAllThreadIds();

        ThreadInfo[] threadInfos = new ThreadInfo[threadIds.length];

        for (int i = 0; i < threadIds.length; i++) {
            threadInfos[i] = threadMXBean.getThreadInfo(threadIds[i], stackTraceMaxDepth);
        }

        return threadInfos;
    }
}